import axios from 'axios'
import JSONbig from 'json-bigint'
import { getNativeToken, sendUserUnauthorized } from '@/utils/native'
import router from '@/router/index'
import afterEndLang from '@/i18n/afterLangH5'
import { $t } from '@/i18n/index'
import { getToken, removeToken } from '@/utils/cookie'
// 错误码的处理
const funcErrCode = (errCode, resp_msg) => {
  if (errCode) {
    if (afterEndLang.some((item) => item.key === errCode)) {
      resp_msg = $t(`${errCode}`)
    } else {
      resp_msg = `${$t('emp_err_unkown')}${' '}${errCode}`
    }
  }
  return resp_msg
}

let codeArr = []
/**
 * @description 在规定时间内，相同的错误码只展示一次错误信息
 */
const throttleErrorPopup = (code, message, delay = 3000) => {
  const isExist = codeArr.find((item) => {
    return item.code === code
  })
  if (!isExist) {
    codeArr.push({
      code,
      message,
      time: +new Date()
    })
    // ElMessage({
    //   message,
    //   type: 'error',
    //   duration: delay
    // })
    setTimeout(() => {
      codeArr = codeArr.filter((item) => {
        return +new Date() - item.time < delay
      })
    }, delay)
  }
}

const JSONbigToString = JSONbig({ storeAsString: true })

// 创建一个 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API, // 所有的请求地址前缀部分
  timeout: 60000, // 请求超时时间毫秒
  withCredentials: false, // 异步请求携带cookie
  headers: {
    // 设置后端需要的传参类型
    // 'Content-Type': 'application/json',
    // 'token': 'your token',
    // 'X-Requested-With': 'XMLHttpRequest',
  },
  // 解决后端返回Long类型的数据前端精度丢失问题
  transformResponse: [
    function (data) {
      try {
        // 转换
        return JSONbigToString.parse(data)
      } catch (err) {
        // 转换失败就直接按原数据返回
        return data
      }
    }
  ]
})

// 添加请求拦截器
service.interceptors.request.use(
  (config) => {
    console.log('request-请求数据', config)
    config.showErrMsg =
      config.showErrMsg === undefined || Boolean(config.showErrMsg)
    config.Authorization =
      config.Authorization === undefined || Boolean(config.Authorization)

    // 是否需要设置 token
    if (config.Authorization) {
      // 让每个请求携带原生token 请根据实际情况自行修改
      getNativeToken()
      const token = getToken()
      config.headers.Authorization =
        config.headers.Authorization || `Bearer ${token}`
    }
    config.params = {
      ...config.params,
      _t: +new Date()
    }
    return config
  },
  (error) => {
    // 对请求错误做些什么
    console.log('request-error', error)
    return Promise.reject(error)
  }
)

// 添加响应拦截器
service.interceptors.response.use(
  (response) => {
    // console.log('response', response)
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    // dataAxios 是 axios 返回数据中的 data
    const dataAxios = response.data
    console.log(response, 'responseresponse')
    // 这个状态码是和后端约定的
    const code = dataAxios.errorCode
    // 文件流传输特殊处理
    let dis = response.headers['content-disposition']
    let fileName = ''
    if (dis) {
      let fileNames = dis.split('attachment;filename=')[1]
      if (fileNames) fileName = decodeURIComponent(fileNames)
    }
    // 统一错误提示
    const errCode = response.data.resp_code
    if (
      response.config.showErrMsg &&
      ((errCode && errCode !== 200) || response.data.code)
    ) {
      let resp_msg = response.data.resp_msg
      resp_msg = funcErrCode(errCode, resp_msg)
      if (errCode !== 20065) {
        throttleErrorPopup(errCode, resp_msg || response.data.resp_msg)
      }
    }
    if (code === 401) {
      sendUserUnauthorized()
      removeToken()
      // router.replace('/login')
    }
    return fileName ? response : dataAxios
  },
  (error) => {
    console.log('response-error', error)
    const { message, response, config } = error
    // 超出 2xx 范围的状态码都会触发该函数。 对响应错误做点什么
    // 401 用户权限过期
    if (error.response.status === 401) {
      sendUserUnauthorized()
      removeToken()
      // router.replace('/login')
      return
    }

    if (config.showErrMsg) {
      let resp_msg = error.response.data.resp_msg
      const errCode = response.data.resp_code
      resp_msg = funcErrCode(errCode, resp_msg)
      throttleErrorPopup(errCode, resp_msg || message || response.data.resp_msg)
    }
    return Promise.reject(error)
  }
)

export default service
